﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObjectLibrary;
using Microsoft.Xna.Framework;
using Particle3DEffect;
using Primitives3D;

using FighterLibrary;namespace AIProcessor
{
    public class ProControl : ComputerControl
    {
        public ProControl(Fighter fighter, int team)
        {
            _fighter = fighter;
            _team = team;
        }
        public override void UpdateAction(Word outsideWord,Game game)
        {
            
            fireTime++;

            if (_targetFoe == null || _targetFoe.CurrentState == Fighter.State.dead)
            {
                _targetFoe = GetNewTarget(outsideWord);
            }
            else
            {
                float value = GetFitnessValue(_targetFoe, outsideWord.ListPlayers[_team]);
                float fireValue = GetFireFitnessValue(_targetFoe, outsideWord.ListPlayers[_team]);
                if (value > fireValue && value > 0)
                {
                    if (MoveToFoe(_targetFoe, 30, 5, 4))
                    {
                        if (Fighter.getDeltaRotaionY(_fighter.LookRotationY, _fighter.RotationY) < MathHelper.PiOver4
                            && _targetFoe.CurrentState != Fighter.State.actack)
                        {
                            if (_fighter.CurrentState == Fighter.State.defend && randomEngine.Next(3) > 0)
                                return;
                            if (randomEngine.Next(3) > 50)
                                _fighter.AddToComboQueue(Move.Strike.PUNCH);
                            else
                                _fighter.AddToComboQueue(Move.Strike.KICK);

                            _fighter.Actack();
                        }
                        else
                        {
                            _fighter.Defend();
                        }
                    }
                }
                else if (value < fireValue && fireValue > 50)
                {
                    if (fireTime > startFireTime)
                    {
                        startFireTime = 100 + randomEngine.Next(10);
                        fireTime = 0;
                        _fighter.EnergySpheres.Add(new EnergySphere(game));
                        _fighter.ThrowEnergySphere(_targetFoe.CurrentPosition + new Vector3(
                    (float)randomEngine.NextDouble() * 2 - 1, (float)randomEngine.NextDouble() * 2, (float)randomEngine.NextDouble() * 2 - 1
                    ));
                    }
                    else 
                    {
                        _fighter.IsFired = true;
                        RandomAcction();
                    }
                }
                else
                {
                    _targetFoe = GetNewTarget(outsideWord);
                    RandomAcction();
                }
            }
        }
        override protected float GetFitnessValue(Fighter fighter, List<Fighter> listFriends)
        {
            Vector3 dPos = fighter.CurrentPosition - _fighter.CurrentPosition;
            float d = dPos.Length();
            float distantPoint = (100 / (d + 1)) * (100 / (d + 1));
            float friendsPoint = 0;
            int friendCount = 0;
            for (int i = 0; i < listFriends.Count; i++)
            {
                if (listFriends[i] != _fighter && (listFriends[i].CurrentPosition - fighter.CurrentPosition).Length() < 10)
                    friendCount++;
                    
            }
            friendsPoint = -10*((1 - friendCount) * (1 - friendCount) - 4);

            float hpPoint = (Fighter.MAX_HP - fighter.Hp)/2;
            return distantPoint + friendsPoint + hpPoint;
        }

        public bool MoveToFoe(Fighter foe,float safeRadius,float actackRadius, float radius)
        {

            Vector3 dPos = foe.CurrentPosition - _fighter.CurrentPosition;
            float d = dPos.Length();
            float rotation = _fighter.GetVecterRotation(dPos);
            _fighter.LookRotationY = rotation;
            if (d <= radius)
            {
                return true;
            }
            else if (d<= actackRadius ||  d >= safeRadius)
            {
                if (Fighter.getDeltaRotaionY(_fighter.LookRotationY, _fighter.RotationY) < MathHelper.PiOver4)
                {

                    _fighter.Run();
                }
                else
                {

                    _fighter.Idle();
                }
            }

            else if( Fighter.getDeltaRotaionY(MathHelper.Pi + rotation, foe.RotationY) < MathHelper.Pi)
            {
                _fighter.Run();
                float reDirect = MathHelper.Pi + rotation;
                if(reDirect >= MathHelper.TwoPi)
                    reDirect -= MathHelper.TwoPi;
                if (reDirect < foe.RotationY)
                    _fighter.LookRotationY = rotation + MathHelper.PiOver4;
                else
                    _fighter.LookRotationY = rotation - MathHelper.PiOver4;
            }

            return false;
        }
    }
}
